/**
 * Session buffer interface
 */

#include "session.h"

////////////////////////////////////////////////////////////////////////////////
// all SB unit size must more than DATBUF_MAX_BUF_CNT
#define BASIC_SB_COUNT 32

////////////////////////////////////////////////////////////////////////////////
static session_buffer_t sb_list[BASIC_SB_COUNT];

static void SessionSbInit(void)
{
	memset(sb_list, 0, sizeof(sb_list));
}

static session_buffer_t *SessionSbAlloc(psysbuf_t buf)
{
	int i;
	uint32_t flags;
	session_buffer_t *sb;

	if (buf == NULL)
		return NULL;

	for (i = 0; i < BASIC_SB_COUNT; i++)
	{
		sb = &sb_list[i];
		if (sb->buf == NULL) {
			sb->buf = buf;
			break;
		}
		sb = NULL;
	}

	return sb;
}

static psysbuf_t SessionSbSwitchFree(session_buffer_t *sb)
{
	uint32_t flags;
	psysbuf_t buf = NULL;

	if (sb == NULL)
		return NULL;

	buf = sb->buf;
	sb->buf = NULL;

	return buf;
}

static session_buffer_t *SessionBufferPush_(struct SESSION *session, psysbuf_t buf)
{
	session_buffer_t *sb;
	if (session == NULL || buf == NULL)
		return NULL;

	sb = SessionSbAlloc(buf);
	if (sb != NULL) {
		slists_init(&(sb->list));
		sb->list.group = &session->buffer_group;
		slists_put(&(sb->list));
	}

	return sb;
}

////////////////////////////////////////////////////////////////////////////////
void SessionInitAll(void)
{
	/* data init */
	SessionSbInit();
}

// every module should be init this
void SessionBufferInit(struct SESSION *session)
{
	if (session == NULL)
		return;

	// init group and free
	slists_group_init(&session->buffer_group);
}

session_buffer_t *SessionBufferPush(struct SESSION *session, psysbuf_t buf)
{
	session_buffer_t *sb = SessionBufferPush_(session, buf);
	if (sb != NULL) {
		//recall buffer changed function);
	}
	return sb;
}

psysbuf_t SessionBufferPop(struct SESSION *session)
{
	psysbuf_t buf = NULL;
	session_buffer_t *sb;
	if (session == NULL)
		return NULL;
	sb = (session_buffer_t *)slists_get(&session->buffer_group);
	if (sb) {
		buf = SessionSbSwitchFree(sb);
	}
	return buf;
}

int SessionBufferTopNum(struct SESSION *session)
{
	if (session == NULL)
		return 0;
	return slists_topnum(&session->buffer_group);
}

void SessionBufferDeInit(struct SESSION *session)
{
	psysbuf_t buf = NULL;
	if (session == NULL)
		return;

	do {
		buf = SessionBufferPop(session);
		if (buf) {
			sysbuf_free(buf);
		}
	} while (buf != NULL);

	slists_group_init(&session->buffer_group);
}
